﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using XQT.Core.TypeEx;
using Think.Core;
using Think.Core.Interfaces;

namespace Think.Extend
{
    /// <summary>
    /// 类型扩展
    /// </summary>
    public static class TypeExtend
    {
        static Dictionary<Type, DbType> typeToDbType = new Dictionary<Type, DbType>();
        static TypeExtend()
        {

            typeToDbType[typeof(byte)] = DbType.Byte;
            typeToDbType[typeof(sbyte)] = DbType.SByte;
            typeToDbType[typeof(short)] = DbType.Int16;
            typeToDbType[typeof(ushort)] = DbType.UInt16;
            typeToDbType[typeof(int)] = DbType.Int32;
            typeToDbType[typeof(uint)] = DbType.UInt32;
            typeToDbType[typeof(long)] = DbType.Int64;
            typeToDbType[typeof(ulong)] = DbType.UInt64;
            typeToDbType[typeof(float)] = DbType.Single;
            typeToDbType[typeof(double)] = DbType.Double;
            typeToDbType[typeof(decimal)] = DbType.Decimal;
            typeToDbType[typeof(bool)] = DbType.Boolean;
            typeToDbType[typeof(string)] = DbType.String;
            typeToDbType[typeof(char)] = DbType.StringFixedLength;
            typeToDbType[typeof(Guid)] = DbType.Guid;
            typeToDbType[typeof(DateTime)] = DbType.DateTime;
            typeToDbType[typeof(DateTimeOffset)] = DbType.DateTimeOffset;
            typeToDbType[typeof(TimeSpan)] = DbType.Time;
            typeToDbType[typeof(byte[])] = DbType.Binary;
            typeToDbType[typeof(byte?)] = DbType.Byte;
            typeToDbType[typeof(sbyte?)] = DbType.SByte;
            typeToDbType[typeof(short?)] = DbType.Int16;
            typeToDbType[typeof(ushort?)] = DbType.UInt16;
            typeToDbType[typeof(int?)] = DbType.Int32;
            typeToDbType[typeof(uint?)] = DbType.UInt32;
            typeToDbType[typeof(long?)] = DbType.Int64;
            typeToDbType[typeof(ulong?)] = DbType.UInt64;
            typeToDbType[typeof(float?)] = DbType.Single;
            typeToDbType[typeof(double?)] = DbType.Double;
            typeToDbType[typeof(decimal?)] = DbType.Decimal;
            typeToDbType[typeof(bool?)] = DbType.Boolean;
            typeToDbType[typeof(char?)] = DbType.StringFixedLength;
            typeToDbType[typeof(Guid?)] = DbType.Guid;
            typeToDbType[typeof(DateTime?)] = DbType.DateTime;
            typeToDbType[typeof(DateTimeOffset?)] = DbType.DateTimeOffset;
            typeToDbType[typeof(TimeSpan?)] = DbType.Time;
            typeToDbType[typeof(Object)] = DbType.Object;
        }

        /// <summary>
        /// 包装类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static TypeWraper Wrap(this Type type)
        {
            return TypeWraper.GetTypeWrap(type);
        }
        /// <summary>
        /// 成员动态调用（非泛型）
        /// </summary>
        /// <param name="info">MemberInfo</param>
        /// <param name="instance">实例</param>
        /// <param name="args">参数</param>
        /// <returns>VoidResult||object</returns>
        public static object DynInvoke(this MemberInfo info, object instance, params object[] args)
        {
            return info == null ? Constants.Void : Think.Core.DynamicOpr.MemberInvoker.Invoke(info, instance, args);
        }
        /// <summary>
        /// 参数类型是否一致
        /// </summary>
        /// <param name="ps"></param>
        /// <param name="types"></param>
        /// <returns></returns>
        public static bool ParameterTypeEquals(this ParameterInfo[] ps, Type[] types)
        {
            if (ps.Length == types.Length)
            {
                if (ps.Length == 0)
                {
                    return true;
                }
                for (int i = 0; i < ps.Length; i++)
                {
                    if (ps[i].ParameterType != types[i])
                    {
                        return false;
                    }
                }
                return true;
            }
            return false;
        }

        /// <summary>
        /// 类型转换
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object ChangeType(this object value, Type type)
        {
            if (type == value.GetType()) return value;
            if (value == null || value is DBNull)
            {
                if (!type.CheckValueType()) { return type.New(); }
                return type.Default();
            }
            if (type == typeof(bool))
            {
                if (value == null || value is DBNull) { return false; }
                if (value is string)
                {
                    return value.Equals("1") || string.Compare(value + "", "true", true) == 0;
                }
                if (value is int) { return ((int)value) > 0; }
                return false;
            }
            if (type == typeof(string))
            {
                return value + "";
            }
            if (type.IsEnum)
            {
                if (value is string)
                    return Enum.Parse(type, value + "");
                else
                    return Enum.ToObject(type, value);
            }
            if (!type.IsInterface && type.IsGenericType)
            {
                Type innerType = type.GetGenericArguments()[0];
                object innerValue = ChangeType(value, innerType);
                return type.New(innerValue);// Activator.CreateInstance(type, new object[] { innerValue });
            }
            if (value is string && type == typeof(Guid))
            {
                var gu = Guid.Empty;
                Guid.TryParse(value + "", out gu);
                return gu;
            }
            if (value is string && type == typeof(Version)) return new Version(value + "");
            if (!(value is IConvertible)) return value;
            return Convert.ChangeType(value, type);
        }

        /// <summary>
        /// 类型转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T ChangeType<T>(this object obj)
        {
            if (obj == null || obj is DBNull)
            {
                return default(T);
            }

            var t = typeof(T);

            return (T)ChangeType(obj, t);
        }
        /// <summary>
        /// 类型默认值
        /// </summary>
        /// <param name="t"></param>
        /// <param name="nullValue">为null时的自定义默认值</param>
        /// <returns></returns>
        public static object Default(this Type t, object nullValue = null)
        {
            return TypeWraper.TypeDefault(t) ?? nullValue;
        }
        /// <summary>
        /// 是否匿名类
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool IsAnonymousType(this Type t)
        {
            return t.Name.StartsWith("<>");
        }

        #region 生成类型数组
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1>()
        {
            return new Type[] { typeof(T1) };
        }
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1, T2>()
        {
            return new Type[] { typeof(T1), typeof(T2) };
        }
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1, T2, T3>()
        {
            return new Type[] { typeof(T1), typeof(T2), typeof(T3) };
        }
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1, T2, T3, T4>()
        {
            return new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) };
        }
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1, T2, T3, T4, T5>()
        {
            return new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) };
        }
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <typeparam name="T6"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1, T2, T3, T4, T5, T6>()
        {
            return new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) };
        }
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <typeparam name="T6"></typeparam>
        /// <typeparam name="T7"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1, T2, T3, T4, T5, T6, T7>()
        {
            return new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) };
        }
        /// <summary>
        /// 生成类型数组
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <typeparam name="T6"></typeparam>
        /// <typeparam name="T7"></typeparam>
        /// <typeparam name="T8"></typeparam>
        /// <returns></returns>
        public static Type[] Types<T1, T2, T3, T4, T5, T6, T7, T8>()
        {
            return new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) };
        }
        #endregion

        #region 方法处理
        /// <summary>
        /// 
        /// </summary>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="genTypes"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod(this Type t, string name, Type[] genTypes = null, Type[] argTypes = null)
        {
            argTypes = argTypes ?? Type.EmptyTypes;
            if (genTypes == null || genTypes.Length == 0)
            {
                return t.GetMethod(name, argTypes);
            }
            var methods = t.GetMethods().Where(c => c.Name.Equals(name) && c.IsGenericMethod);

            foreach (var m in methods)
            {
                var gas = m.GetGenericArguments();
                if (gas.Length == genTypes.Length)
                {
                    var cmi = m.MakeGenericMethod(genTypes);
                    if (argTypes.Length == 0 || cmi.GetParameters().ParameterTypeEquals(argTypes))
                    { return cmi; }
                }
            }
            return null;


        }

        #region 泛型参数方法信息确认
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1) }, argTypes);
        }
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1, T2>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1), typeof(T2) }, argTypes);
        }
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1, T2, T3>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1), typeof(T2), typeof(T3) }, argTypes);
        }
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1, T2, T3, T4>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, argTypes);
        }
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1, T2, T3, T4, T5>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) }, argTypes);
        }
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <typeparam name="T6"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1, T2, T3, T4, T5, T6>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) }, argTypes);
        }
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <typeparam name="T6"></typeparam>
        /// <typeparam name="T7"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1, T2, T3, T4, T5, T6, T7>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) }, argTypes);
        }
        /// <summary>
        /// 泛型参数方法信息确认
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <typeparam name="T6"></typeparam>
        /// <typeparam name="T7"></typeparam>
        /// <typeparam name="T8"></typeparam>
        /// <param name="t"></param>
        /// <param name="name"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static MethodInfo EnsureMethod<T1, T2, T3, T4, T5, T6, T7, T8>(this Type t, string name, Type[] argTypes = null)
        {
            return t.EnsureMethod(name, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) }, argTypes);
        }

        #endregion

        #endregion

        #region 构造处理
        /// <summary>
        /// 确认构造函数，泛型需传入类型数组
        /// </summary>
        /// <param name="t"></param>
        /// <param name="genTypes">泛型类型</param>
        /// <param name="argTypes">构造参数类型</param>
        /// <returns></returns>
        public static ConstructorInfo EnsureConstructor(this Type t, Type[] genTypes = null, Type[] argTypes = null)
        {
            var ct = t;
            if (t.IsGenericTypeDefinition)
            {
                ct = t.MakeGenericType(genTypes);
            }
            argTypes = argTypes ?? Type.EmptyTypes;
            return ct.GetConstructor(argTypes);
        }

        #region 泛型构造信息确认
        /// <summary>
        /// 泛型构造信息确认
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static ConstructorInfo EnsureConstructor<T>(this Type t, Type[] argTypes = null)
        {
            return EnsureConstructor(t, new Type[] { typeof(T) }, argTypes);
        }
        /// <summary>
        /// 泛型构造信息确认
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static ConstructorInfo EnsureConstructor<T, T1>(this Type t, Type[] argTypes = null)
        {
            return EnsureConstructor(t, new Type[] { typeof(T), typeof(T1) }, argTypes);
        }
        /// <summary>
        /// 泛型构造信息确认
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static ConstructorInfo EnsureConstructor<T, T1, T2>(this Type t, Type[] argTypes = null)
        {
            return EnsureConstructor(t, new Type[] { typeof(T), typeof(T1), typeof(T2) }, argTypes);
        }
        /// <summary>
        /// 泛型构造信息确认
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static ConstructorInfo EnsureConstructor<T, T1, T2, T3>(this Type t, Type[] argTypes = null)
        {
            return EnsureConstructor(t, new Type[] { typeof(T), typeof(T1), typeof(T2), typeof(T3) }, argTypes);
        }
        /// <summary>
        /// 泛型构造信息确认
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <returns></returns>
        public static ConstructorInfo EnsureConstructor<T, T1, T2, T3, T4>(this Type t, Type[] argTypes = null)
        {
            return EnsureConstructor(t, new Type[] { typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, argTypes);
        }
        #endregion
        /// <summary>
        /// 调用构造函数，创建类型实例
        /// </summary>
        /// <param name="t"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object New(this Type t, params object[] args)
        {
            if (args.HasElement())
            {
                var types = Type.GetTypeArray(args);
                return EnsureConstructor(t, argTypes: types).DynInvoke(null, args);
            }
            return EnsureConstructor(t).DynInvoke(null, args);
        }
        /// <summary>
        /// 调用构造函数，创建类型实例
        /// </summary>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object New(this Type t, Type[] argTypes = null, params object[] args)
        {
            return EnsureConstructor(t, @argTypes: argTypes).DynInvoke(null, args);
        }
        /// <summary>
        /// 调用【泛型】构造函数，创建类型实例
        /// </summary>
        /// <param name="t"></param>
        /// <param name="genaricTypes"></param>
        /// <param name="argTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object NewGenaric(this Type t, Type[] genaricTypes, Type[] argTypes = null, params object[] args)
        {
            return EnsureConstructor(t, genaricTypes, @argTypes: argTypes).DynInvoke(null, args);
        }
        #region 泛型实例创建
        /// <summary>
        /// 泛型实例创建
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object New<T>(this Type t, Type[] argTypes = null, params object[] args)
        {
            return EnsureConstructor<T>(t, argTypes).DynInvoke(args);
        }
        /// <summary>
        /// 泛型实例创建
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object New<T, T1>(this Type t, Type[] argTypes = null, params object[] args)
        {
            return EnsureConstructor<T, T1>(t, argTypes).DynInvoke(args);
        }
        /// <summary>
        /// 泛型实例创建
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object New<T, T1, T2>(this Type t, Type[] argTypes = null, params object[] args)
        {
            return EnsureConstructor<T, T1, T2>(t, argTypes).DynInvoke(args);
        }
        /// <summary>
        /// 泛型实例创建
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object New<T, T1, T2, T3>(this Type t, Type[] argTypes = null, params object[] args)
        {
            return EnsureConstructor<T, T1, T2, T3>(t, argTypes).DynInvoke(args);
        }
        /// <summary>
        /// 泛型实例创建
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <param name="t"></param>
        /// <param name="argTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object New<T, T1, T2, T3, T4>(this Type t, Type[] argTypes = null, params object[] args)
        {
            return EnsureConstructor<T, T1, T2, T3, T4>(t, argTypes).DynInvoke(args);
        }
        #endregion
        #endregion

        /// <summary>
        /// 值类型或string或 guid
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool CheckValueType(this Type t)
        {
            return t.Wrap().IsValueType;
        }


        /// <summary>
        /// 是否派生自基类
        /// </summary>
        /// <param name="t"></param>
        /// <param name="baseType"></param>
        /// <returns></returns>
        public static bool DerivedFrom(this Type t, Type baseType)
        {
            if (t.BaseType == baseType) return true;
            if (baseType.IsInterface)
            {
                return t.GetInterface(baseType.FullName) != null || (t.GetInterfaces().FirstOrDefault(c => c == baseType) != null);
            }
            return t.IsSubclassOf(baseType);
        }
        /// <summary>
        /// 确认集合元素类型
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public static Type EnsureElementType(this Type t)
        {
            var el = t.GetElementType();
            if (el == null)
            {
                if (t.IsGenericType && !t.IsGenericTypeDefinition)
                {
                    var cp = t.GetGenericArguments();
                    if (t.DerivedFrom(typeof(IDictionary)))
                    {
                        el = typeof(KeyValuePair<,>).MakeGenericType(cp);
                    }
                    else
                    {
                        return cp[0];
                    }
                }
            }
            return el;
        }


        /// <summary>
        /// 获取成员返回类型
        /// </summary>
        /// <param name="mi"></param>
        /// <returns></returns>
        public static Type GetResultType(this MemberInfo mi)
        {
            if (mi.MemberType == MemberTypes.Property)
            {
                return ((PropertyInfo)mi).PropertyType;
            }
            else if (mi.MemberType == MemberTypes.Field)
            {
                return ((FieldInfo)mi).FieldType;
            }
            else if (mi.MemberType == MemberTypes.Method)
            {
                return ((MethodInfo)mi).ReturnType;
            }
            else if (mi.MemberType == MemberTypes.Constructor)
            {
                return mi.ReflectedType;
            }
            return mi.DeclaringType;
        }
        /// <summary>
        /// 获取数据库类型
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static DbType GetDbType(this object obj)
        {
            if (obj is Type)
            {
                return ToDbType((Type)obj);
            }
            else
            {
                var t = obj.GetType();
                var to = t.ToDbType();
                if (to == DbType.Object)
                {
                    var co = obj as IKey;
                    if (co != null)
                    {
                        var o = co.GetKey();
                        return o.GetDbType();
                    }
                }
            }
            return DbType.Object;
        }
        /// <summary>
        /// 获取数据库类型
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public static DbType ToDbType(this Type t)
        {
            if (typeToDbType.ContainsKey(t))
            {
                return typeToDbType[t];
            }
            return DbType.Object;
        }
    }
}
